#include "ClientChecker.hpp"
#include <cstdlib>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

#include "Types.hpp"
#include <cstdlib>
#include "Message.hpp"
#include "JSONParser.hpp"
#include "RequestManager.hpp"
#include "Config.hpp"

using boost::asio::ip::tcp;



namespace netspy
{

void ClientChecker::runCheckers(uint32_t  checkerThreadNumber)
{
	if (!isRunning_)
	{
		for (uint32_t i=0; i<checkerThreadNumber; ++i)
		{
			checkerGroup_.create_thread(boost::bind(&ClientChecker::checkerSession,this));
		}
	}
	isRunning_= true;
}



void ClientChecker::checkerSession()
{

	for(;;)
	{

	   message_ptr message = RequestManager::getInstance().getRequest();
	   message->command=getCommandString(CHECK_STATUS);
	   message_ptr ans(new Message((*message)));
           if(Config::getInstance().isVerbose())
	   {
	   	std::cout << "Sending command" << std:: endl;
           	std::cout << "\tCommand: " << message->command << std::endl;
           	std::cout << "\tHost info: " <<  "ip: " << message->info.ip << " port: " << message->info.port << std::endl;
           	std::cout << "\tHost info: " <<  "hash: " << message->info.hash << std:: endl;
	   }

	   try{

			boost::asio::io_service io_service;
			boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(message->info.ip), message->info.port);
			socket_ptr sock(new tcp::socket(io_service));
			sock->connect(endpoint);

			std::string query = JSONParser::pack((*message));
	        	boost::asio::write((*sock), boost::asio::buffer(query.c_str(),query.length()));

		        char data[DATA_MAX_LENGTH];
        		memset(data,0,DATA_MAX_LENGTH);
			boost::system::error_code error;
        		sock->read_some(boost::asio::buffer(data), error);
        		if (error) throw boost::system::system_error(error); // Some other error.               
			ans = message_ptr(new Message(JSONParser::unpack(data)));
			ans->info.hash=message->info.hash;
        	        if(Config::getInstance().isVerbose())
			{
				for (ServiceList::const_iterator it=ans->service_list.begin(); it != ans->service_list.end(); ++it)
        	        	{
		        		std::cout << "\tHost info: " <<  "Service: " << (*it) << " Status: " << ans->status_map[(*it)] << std::endl;
				}	
       			}
			RequestManager::getInstance().storeResult(ans);
						
	   }
                
	   catch (std::exception& e)
           {
                 //   std::cerr << "Exception: " << e.what() << "\n";

		ans->service_list.clear();
		if (Config::getInstance().isVerbose())
		{
			std::cout << "\tHost info: dead" << std::endl;
			RequestManager::getInstance().storeResult(ans);
		}  
           }

}
}
}
